/**
 * Canvas管理器 - 负责Canvas的设置和基本绘制
 */
export class CanvasManager {
  private container: HTMLElement
  private canvas: HTMLCanvasElement
  private video?: HTMLVideoElement
  private ctx: CanvasRenderingContext2D
  private resizeObserver?: ResizeObserver
  private videoEventHandlers: { event: string; handler: () => void }[] = []

  constructor(
    container: HTMLElement,
    canvas: HTMLCanvasElement,
    video?: HTMLVideoElement
  ) {
    this.container = container
    this.canvas = canvas
    this.video = video
    const context = this.canvas.getContext('2d', { 
      alpha: true,
      desynchronized: true 
    })
    
    if (!context) {
      throw new Error('无法获取 Canvas 2D 上下文')
    }
    
    this.ctx = context
    this.setupCanvas()
    this.setupResizeObserver()
  }

  /**
   * 设置Canvas尺寸和位置
   */
  setupCanvas(): void {
    if (!this.video) {
      // 没有视频时，使用容器尺寸
      const rect = this.container.getBoundingClientRect()
      this.canvas.width = rect.width
      this.canvas.height = rect.height
      this.canvas.style.width = `${rect.width}px`
      this.canvas.style.height = `${rect.height}px`
      return
    }

    const videoRect = this.getVideoDisplayRect()
    
    // 设置 canvas 尺寸匹配视频显示区域
    this.canvas.width = videoRect.width
    this.canvas.height = videoRect.height
    
    // 设置 canvas 位置
    this.canvas.style.position = 'absolute'
    this.canvas.style.left = `${videoRect.left}px`
    this.canvas.style.top = `${videoRect.top}px`
    this.canvas.style.width = `${videoRect.width}px`
    this.canvas.style.height = `${videoRect.height}px`
    this.canvas.style.pointerEvents = 'none'
  }

  /**
   * 获取视频显示区域
   */
  private getVideoDisplayRect(): { left: number; top: number; width: number; height: number } {
    if (!this.video) {
      return { left: 0, top: 0, width: 0, height: 0 }
    }

    const containerRect = this.container.getBoundingClientRect()
    
    const videoAspect = this.video.videoWidth / this.video.videoHeight
    const containerAspect = containerRect.width / containerRect.height

    let displayWidth: number
    let displayHeight: number
    let left: number
    let top: number

    if (videoAspect > containerAspect) {
      // 视频更宽，以宽度为准
      displayWidth = containerRect.width
      displayHeight = containerRect.width / videoAspect
      left = 0
      top = (containerRect.height - displayHeight) / 2
    } else {
      // 视频更高，以高度为准
      displayHeight = containerRect.height
      displayWidth = containerRect.height * videoAspect
      left = (containerRect.width - displayWidth) / 2
      top = 0
    }

    return { left, top, width: displayWidth, height: displayHeight }
  }

  /**
   * 设置尺寸观察器
   */
  private setupResizeObserver(): void {
    this.resizeObserver = new ResizeObserver(() => {
      this.setupCanvas()
    })
    this.resizeObserver.observe(this.container)

    // 监听视频加载事件
    if (this.video) {
      const handleVideoResize = () => {
        this.setupCanvas()
      }

      const events = ['loadedmetadata', 'resize', 'loadeddata']
      events.forEach(eventName => {
        this.video!.addEventListener(eventName, handleVideoResize)
        this.videoEventHandlers.push({ event: eventName, handler: handleVideoResize })
      })
    }
  }

  /**
   * 强制清理Canvas
   */
  forceCleanCanvas(): void {
    this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
    this.ctx.setTransform(1, 0, 0, 1, 0, 0)
    this.ctx.globalAlpha = 1
    this.ctx.globalCompositeOperation = 'source-over'
  }

  /**
   * 清空Canvas
   */
  clearCanvas(): void {
    this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
  }

  /**
   * 获取绘图上下文
   */
  getContext(): CanvasRenderingContext2D {
    return this.ctx
  }

  /**
   * 获取Canvas尺寸
   */
  getSize(): { width: number; height: number } {
    return {
      width: this.canvas.width,
      height: this.canvas.height
    }
  }

  /**
   * 清理资源
   */
  destroy(): void {
    if (this.resizeObserver) {
      this.resizeObserver.disconnect()
    }

    // 移除视频事件监听
    if (this.video) {
      this.videoEventHandlers.forEach(({ event, handler }) => {
        this.video!.removeEventListener(event, handler)
      })
    }
    this.videoEventHandlers = []
  }
}

